﻿#pragma once
#include <opencv2/core.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "seeta/FaceLandmarker.h"
#include "seeta/FaceDetector.h"
#include "seeta/FaceAntiSpoofing.h"
#include "seeta/Common/Struct.h"
#include "seeta/CTrackingFaceInfo.h"
#include "seeta/FaceTracker.h"
#include "seeta/FaceRecognizer.h"
#include "seeta/QualityAssessor.h"
#include "seeta/QualityOfPoseEx.h"
#include "seeta/QualityOfLBN.h"
#include "seeta/EyeStateDetector.h"

#include <map>
#include <fstream>
#include <iostream>
#include <stdio.h>
#define NO_RUN 0;
#define RUNNING 1
#define MOVING 2;
#define	COMPLISH 3;
#define EXCEPTION 4;

using namespace std;
typedef pair<seeta::EyeStateDetector::EYE_STATE,
	seeta::EyeStateDetector::EYE_STATE> EYESTATE_PAIR ;

class FaceAction
{
public:
	const int EYE_LEFT_BLINK_ACTION = 1;
	const int EYE_RIGHT_BLINK_ACTION = 2;
	const int EYE_ALL_BLINK_ACTION = 3;
	const int TURN_LEFT_ACTION = 4;
	const int TURN_RIGHT_ACTION = 5;
	const int TURN_UP_ACTION = 6;
	const int MOUTH_ACTION = 7;
	const int EYE_ROTATION_LEFT_ACTION = 8;
	const int EYE_ROTATION_RIGHT_ACTION = 9;


	int INIT = 0;
	string modelpath;
    seeta::QualityOfPoseEx* QP;
    seeta::FaceDetector* FD;
    seeta::FaceLandmarker* flm68;
    seeta::FaceLandmarker* flm5;
//	seeta::EyeStateDetector* ESD;
	seeta::v3::QualityResult checkRes;
	cv::Mat imgMat;
	cv::Mat imgMat_gray;
	SeetaImageData* imgData_gray;
	SeetaImageData* imgData;
	SeetaRect* fRect;
	vector<SeetaPointF>* i_points5;
	vector<SeetaPointF>* points5;
	vector<SeetaPointF>* i_points68;
	vector<SeetaPointF>* points68;
	FaceAction(seeta::FaceLandmarker* flm68,
		seeta::FaceLandmarker* flm5, seeta::EyeStateDetector* ESD,
		seeta::FaceDetector* FD, seeta::QualityOfPoseEx* QP){
		contructContent(flm68, flm5, ESD, FD, QP);
	}
    FaceAction(const std::string modelpath) {
		contructContent(modelpath);
	}
	FaceAction(SeetaImageData& imgData, SeetaRect& fRect, string modelpath);
	FaceAction(cv::Mat& imgMat, SeetaRect& fRect, string modelpath);

	int inferAction(cv::Mat& img);
	int inferEyeRotate(cv::Mat& img);

    static seeta::QualityOfPoseEx* getQualityOfPoseEx(const seeta::ModelSetting& setQP);
    static seeta::FaceDetector* getFaceDetector(const seeta::ModelSetting& setFD);
    static seeta::FaceLandmarker* getFaceLandmarker68(const seeta::ModelSetting& s68);
    static seeta::FaceLandmarker* getFaceLandmarker5(const seeta::ModelSetting& s5);
//	seeta::EyeStateDetector* getEyeStateDetector(string modelpath);

    void contructContent(const std::string modelpath);
	void contructContent(seeta::FaceLandmarker* flm68,
		seeta::FaceLandmarker* flm5, seeta::EyeStateDetector* ESD,
		seeta::FaceDetector* FD, seeta::QualityOfPoseEx* QP);
	bool init_points(vector<SeetaPointF>& i_points5, vector<SeetaPointF>& i_points68);
	bool init_points();
	void setPoints(vector<SeetaPointF>& points);
	void init_ImageData(SeetaImageData& imgData, SeetaRect& fRect);
	void init_Mat(cv::Mat& imgMat, SeetaRect& fRect);
	void setPoints68();
	void setPoints5();
	cv::Mat drawPoints(int pointsSize, bool showNumber = false);
     cv::Mat drawPoints(cv::Mat& mat, bool showNumber = false, int pointsSize = 68);
	void resetAction();

	int LEFT = 0;
	int RIGHT = 1;
	int EYE_ROTATION_LEFT = 0;
	int EYE_ROTATION_RIGHT = 0;
	cv::Point LEye_InitCenter;
	cv::Point REye_InitCenter;
	cv::Point LEye_RltCenter;
	cv::Point REye_RltCenter;
	cv::Point LEye_Center;
	cv::Point REye_Center;
	cv::Mat EFrame_left;
	cv::Mat EFrame_right;
	cv::Mat getEyeFrame(int eye);
	cv::Mat getIrisFrame(cv::Mat& eye_frame, int threshould);
	float getIrisSize(cv::Mat iris_frame);
	int getBestThreshould(cv::Mat eye_frame);
	void getEyeCenter();
	cv::Mat showEyeCenter(cv::Mat& mat);
	int checkEyeRotation();

	int INIT_TURNLEFT_ANGLE;
	int INIT_TURNRIGHT_ANGLE;
	int INIT_TURNUP_ANGLE;
	int TURN_LEFT = 0;
	int TURN_RIGHT = 0;
	int TURN_DOWN = 0;
	int TURN_UP = 0;
	int LEFT_FRAMES = 0;
	int RIGHT_FRAMES = 0;
	int UP_FRAMES = 0;
	int distance(int d1, int d2);
	int calcAngle(int d1, int d2, int d3);
	int checkTurn(int turnType);
	int checkAllTurn();


	int LEFT_BLINK = 0;
	int RIGHT_BLINK = 0;
	int ALL_BLINK = 0;
	EYESTATE_PAIR getEyestate();
	int checkEyes(seeta::EyeStateDetector::EYE_STATE leftstate, 
		seeta::EyeStateDetector::EYE_STATE rightstate, int eyeType);
	int checkEyes(int eyeType);
	int checkAllEyes();


	int OPEN_MOUTH = 0;
	int checkMouth();

	int checkAllAction();
};

